
#include <BFont>
#include <BChangeEvent>
#include <BFocusEvent>
#include <BPainter>
#include <BButton>

#include <BMessageBox>
#include "member_BMessageBox.h"

using namespace BWE;

#define member					(*(member_BMessageBox*)_ptr)
#define member_allocate()		_ptr = new member_BMessageBox(this)
#define member_release()		delete (member_BMessageBox*)_ptr

BMessageBox* GetMessageBox()
{
	static BHolder<BMessageBox> messageBox = new BMessageBox();
	messageBox->setModal(true);
	return messageBox;
}
Button BMessageBox::about(BWidget *parent, const BString &title, const BString &text, int buttons, Button defaultButton)
{
	BMessageBox* mbox = GetMessageBox();
	mbox->setParent(parent);
	mbox->setTitle(title);
	mbox->setText(text);
	return (Button)mbox->execute();
}
Button BMessageBox::critical(BWidget *parent, const BString &title, const BString &text, int buttons, Button defaultButton)
{
	BMessageBox* mbox = GetMessageBox();
	mbox->setParent(parent);
	mbox->setTitle(title);
	mbox->setText(text);
	mbox->setButtons(buttons);
	mbox->setDefaultButton(defaultButton);
	return (Button)mbox->execute();
}
Button BMessageBox::information(BWidget *parent, const BString &title, const BString &text, int buttons, Button defaultButton)
{
	BMessageBox* mbox = GetMessageBox();
	mbox->setParent(parent);
	mbox->setTitle(title);
	mbox->setText(text);
	mbox->setButtons(buttons);
	mbox->setDefaultButton(defaultButton);
	return (Button)mbox->execute();
}
Button BMessageBox::question(BWidget *parent, const BString &title, const BString &text, int buttons, Button defaultButton)
{
	BMessageBox* mbox = GetMessageBox();
	mbox->setParent(parent);
	mbox->setTitle(title);
	mbox->setText(text);
	mbox->setButtons(buttons);
	mbox->setDefaultButton(defaultButton);
	return (Button)mbox->execute();
}
Button BMessageBox::warning(BWidget *parent, const BString &title, const BString &text, int buttons, Button defaultButton)
{
	BMessageBox* mbox = GetMessageBox();
	mbox->setParent(parent);
	mbox->setTitle(title);
	mbox->setText(text);
	mbox->setButtons(buttons);
	mbox->setDefaultButton(defaultButton);
	return (Button)mbox->execute();
}

BMessageBox::BMessageBox(BWidget* parent) : BDialog(parent)
{
	member_allocate();
	member.buttonLayout = new BHBoxLayout();
	this->setLayout(member.buttonLayout, Part_Bottom);
}
BMessageBox::~BMessageBox()
{
	member_release();
}

void BMessageBox::setText(const BString& text)
{
	if (member.text != text)
	{
		member.text = text;
		this->fresh();
	}
}
const BString& BMessageBox::text() const
{
	return member.text;
}

int BMessageBox::setButtons(int buttons)
{
	clearButtons();
	int b = 1;
	for (int i = 0; i < 32; i++)
	{
		b <<= 1;
		if (buttons & b)
			addButton((Button)b);
	}
	return member.buttonPairs.size();
}
void BMessageBox::addButton(Button button)
{
	if (member.buttonPairs.contain(button))
		return;

	const char* text = member.buttonText(button);
	if (!text)
		return;

	BButton* btn = new BButton(text);
	member.buttonPairs.append(ButtonPair(btn, button));
	member.buttonLayout->addWidget(btn);
	member.connect(btn, Signal_Clicked, &member_BMessageBox::slotButtonClicked);

}
bool BMessageBox::removeButton(Button button)
{
	int index = member.buttonPairs.find(button);
	ButtonPair& bp = member.buttonPairs[index];
	if (bp.button)
	{
		this->removeChild(bp.button);
		member.buttonPairs.remove(button);
		return true;
	}
	return false;
}
void BMessageBox::clearButtons()
{
	while (member.buttonLayout->count())
	{
		BWidget* widget = member.buttonLayout->widget(0);
		this->removeChild(widget);
	}
	member.buttonPairs.clear();
}

int BMessageBox::buttonCount() const
{
	return member.buttonPairs.size();
}
Button BMessageBox::button(int index) const
{
	return member.buttonPairs[index].btn;
}
const BButton* BMessageBox::buttonWidget(int index) const
{
	return member.buttonPairs[index].button;
}

void BMessageBox::setDefaultButton(Button button)
{
	if (member.defaultButton != button)
	{
		member.defaultButton = button;
	}
}
Button BMessageBox::defaultButton() const
{
	return member.defaultButton;
}

BSize BMessageBox::sizeHint() const
{
	BSize hsize = BDialog::sizeHint();
	const BFont* font = this->font();
	if (font)
	{
		BSize textSize = font->textSize(member.text);
		hsize += textSize;
	}
	return hsize + BSize(20, 20);
}

void BMessageBox::showEvent(const BEvent& event)
{
	BDialog::showEvent(event);
	if (member.defaultButton)
	{
		int index = member.buttonPairs.find(member.defaultButton);
		ButtonPair& bp = member.buttonPairs[index];
		if (bp.button)
		{
			bp.button->setFocus(true);
		}
	}
}

void BMessageBox::styleEvent(const BEvent& event)
{
	BDialog::styleEvent(event);
}
void BMessageBox::freshEvent(const BEvent& event)
{
	BDialog::freshEvent(event);
}
void BMessageBox::paintEvent(const BEvent& event)
{
	BDialog::paintEvent(event);

	BPainter painter(this);
	painter.setColor(Color_Text);
	painter.drawText(this->clientRect(), member.text);
}

void BMessageBox::focusEvent(const BFocusEvent& event)
{
	if (event.focus() == Focus_Out)
	{
		if (this->modal() == false)
		{
			//this->hide();
		}
	}
}
